package com.aube.plugin.rank.view;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.aube.plugin.rank.IItemClickListener;
import com.aube.plugin.rank.ILoginChecker;
import com.aube.plugin.rank.OnRefreshEndListener;
import com.aube.plugin.rank.RankNumManager;
import com.aube.plugin.rank.model.CategoryRankModel;
import com.aube.plugin.rank.model.RankModel;
import com.huyn.baseframework.dynamicload.DLLayout;
import com.huyn.baseframework.dynamicload.DynamicLoaderHelper;
import com.huyn.baseframework.dynamicload.IPositionListener;
import com.huyn.baseframework.dynamicload.IPositionManager;
import com.huyn.baseframework.dynamicload.PluginPackageManager;
import com.huyn.baseframework.model.Character;
import com.huyn.baseframework.utils.Constant;
import com.ryg.dynamicload.internal.DLPluginPackage;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by huyaonan on 16/7/13.
 */
public class RankGroup extends DLLayout implements IItemClickListener {

    private List<IPositionListener> mAnimItems = new ArrayList<>();

    private AtomicBoolean mTranslationYSetInit = new AtomicBoolean(false);
    private HashMap<String, Integer> mTranslationYSet = new HashMap<>();
    private List<String> mRankList = new ArrayList<>();

    private String mModuleCode;

    private String mGroupKey;

    private ILoginChecker iLoginChecker;

    public RankGroup(Context context) {
        this(context, null);
    }

    public RankGroup(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RankGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void initViews() {

    }

    public void setLoginChecker(ILoginChecker iLoginChecker) {
        this.iLoginChecker = iLoginChecker;
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = 0;
        if(!mTranslationYSetInit.get()) {
            for (int i = 0; i < getChildCount(); i++) {
                getChildAt(i).measure(widthMeasureSpec, View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
                mTranslationYSet.put(((RankItem) getChildAt(i)).getCId(), height);
                height += getChildAt(i).getMeasuredHeight();
            }

            if(getChildCount() > 0 && getChildAt(0).getMeasuredHeight() > 0)
                mTranslationYSetInit.set(true);
        } else {
            for (int i = 0; i < getChildCount(); i++) {
                getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
                height += getChildAt(i).getMeasuredHeight();
            }
        }

        super.onMeasure(widthMeasureSpec, View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        for(int i=0; i<getChildCount(); i++) {
            View child = getChildAt(i);
            child.layout(0, top, child.getMeasuredWidth(), top + child.getMeasuredHeight());
            child.setTranslationY(mTranslationYSet.get(((RankItem) child).getCId()));
        }
    }

    @Override
    public void fillData(Object o) {
    }

    public void fillData(RankModel data, boolean visible, boolean registToObserver, boolean fromMain) {
        if(data == null)
            return;

        if(data.characters == null || data.characters.size() == 0) {
            getDataByTitles(data, false, fromMain, null);
            return;
        }

        mGroupKey = data.getGroupKey();

        int size = data.characters.size();
        Character model;
        for(int i=0; i<size; i++) {
            model = data.characters.get(i);
            RankItem item = getDLPluginPackage() == null ? new RankItem(getContext()) : (RankItem) DynamicLoaderHelper.loadTargetLayout(context, getDLPluginPackage(), RankItem.class.getName());
            if(item == null)
                continue;
            addView(item, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));

            if(!visible)
                item.setAlpha(0f);
            else
                item.animated();
            RankNumManager.updateItem(mGroupKey, model.relatedId, model.praiseCount);
            if(fromMain)
                RankNumManager.initFavor(mGroupKey, model.relatedId, model.weekPraiseCount);
            else
                RankNumManager.updateFavor(mGroupKey, model.relatedId, model.weekPraiseCount);

            item.setTag(model.relatedId);
            item.setLoginChecker(iLoginChecker);
            item.setDLBridge(mBridge);
            item.setIndex(i);
            item.setGroupKey(mGroupKey);
            item.setWeekStr(data.week);
            item.setTheme(RankNumManager.getTheme(i));
            item.fillData(model);
            item.setRatio(RankNumManager.getItemRatio(mGroupKey, model.relatedId));
            item.setItemClickListener(this);

            if(registToObserver)
                RankNumManager.registRankItem(model.relatedId, item);

            item.setTag(model.relatedId);
            mAnimItems.add(item);
            mRankList.add(model.relatedId);
        }

    }

    public void refresh(RankModel data, boolean fromMain, OnRefreshEndListener listener) {
        getDataByTitles(data, getChildCount() > 0, fromMain, listener);
    }

    public void getDataByTitles(final RankModel data, final boolean update, final boolean fromMain, final OnRefreshEndListener listener) {
        HashMap<String, String> params = new HashMap<>();
        params.put(Constant.API_REQUEST_METHOD, "com.aube.rank.rankData");
        params.put("weeks", data.week);
        params.put("actorIds", data.actorIds);

        Response.Listener<CategoryRankModel> responseListener = new Response.Listener<CategoryRankModel>() {
            @Override
            public void onResponse(CategoryRankModel response) {
                if(listener != null)
                    listener.endLoading();
                if (response == null || !response.success())
                    return;

                updateRankItem(response, data.actorIds, update, fromMain);
            }

            @Override
            public void onErrorResponse(VolleyError error) {
                if(listener != null)
                    listener.endLoading();
            }

            @Override
            public void onStart() {
            }
        };

        if(mBridge != null) {
            mBridge.exeHttpRequest(params, CategoryRankModel.class, null, responseListener);
            return;
        }

        if(iLoginChecker != null) {
            iLoginChecker.exeProxyHttpRequest(params, CategoryRankModel.class, null, responseListener);
            return;
        }
    }

    private void updateRankItem(CategoryRankModel model, String actorIds, boolean update, boolean fromMain) {
        if(model.data == null || model.data.size() == 0) {
            return;
        }
        try {
            RankModel rankModel = model.data.get(0).toRankModel().sort();
            rankModel.actorIds = actorIds;

            //refresh
            if(update)
                update(rankModel.characters);
            else
                fillData(rankModel, true, true, fromMain);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void update(Object data) {
        if(data == null || !(data instanceof List))
            return;

        List<Character> characters = (List<Character>) data;
        int size = characters.size();
        Character model;

        mRankList.clear();
//        mTranslationYSetInit.set(false);
        mTranslationYSet.clear();
        int height = 0;
        if(getChildCount() == size) {
            for(int i=0; i<size; i++) {
                model = characters.get(i);

                //更新数据
                RankNumManager.updateItem(mGroupKey, model.relatedId, model.praiseCount);
                RankNumManager.initFavor(mGroupKey, model.relatedId, model.weekPraiseCount);

                mRankList.add(model.relatedId);
                RankItem item = (RankItem) findViewWithTag(model.relatedId);
                if(height == 0)
                    height = item.getMeasuredHeight();
//                item.setIndex(i);
                item.initTheme(RankNumManager.getTheme(i));
                item.update(model);
                //更新位置
                item.updataRank(i);
//                ((DLLayout) getChildAt(i)).update(model);

                mTranslationYSet.put(model.relatedId, i*height);
            }

        }
        requestLayout();
    }

    @Override
    public void update() {
        for(int i=0; i<getChildCount(); i++) {
            ((DLLayout) getChildAt(i)).update();
        }
    }

    @Override
    public void notifyAnim(int animDelay) {
        if(mAnimItems == null)
            return;
        notifyItemAnim(animDelay + 300);
    }

    public void setModuleCode(String code) {
        this.mModuleCode = code;
    }

    private void notifyItemAnim(int animDelay) {
        int i=0;
        for (IPositionListener item : mAnimItems) {
            item.notifyAnim(animDelay + i*200);
            i++;
        }
    }

    @Override
    public DLPluginPackage getDLPluginPackage() {
        DLPluginPackage pkg = super.getDLPluginPackage();
        if(pkg == null)
            pkg = PluginPackageManager.getInstance().getModule(mModuleCode);
        return pkg;
    }

    @Override
    public void registToManager(IPositionManager iPositionManager) {

    }

    @Override
    public void unreistFromManager(IPositionManager iPositionManager) {

    }

    @Override
    public int[] getLocations() {
        return new int[0];
    }

    @Override
    public void onItemClicked(RankItem rankItem) {
        for(int i=0; i<getChildCount(); i++) {
            RankItem item = (RankItem) getChildAt(i);
            float ratio = RankNumManager.getItemRatio(item.getGroupKey(), item.getCId());
            item.setRatio(ratio);
        }

        HashMap<String, Integer> mYSets = new HashMap<>();

        sortRank(rankItem);

        int itemHeight = getChildAt(0).getMeasuredHeight();

        int i=0;
        for(String id : mRankList) {
            mYSets.put(id, i*itemHeight);
            i++;
        }

        //重新set排行
        for(i=0; i<mRankList.size(); i++) {
            ((RankItem) (findViewWithTag(mRankList.get(i)))).updataRank(i);
        }

        relayoutItems(mYSets);
    }

    /**
     * 倒序排序
     */
    private void sortRank(RankItem rankItem) {
        int i=0;
        int currentIndex=-1;
        int targetIndex=-1;
        for(String s : mRankList) {
            if(s.equalsIgnoreCase(rankItem.getCId()))
                currentIndex = i;

            i++;
        }

        i=0;
        for(String s : mRankList) {
            if(i < currentIndex) {
                if(RankNumManager.getItemRatio(rankItem.getGroupKey(), rankItem.getCId()) > RankNumManager.getItemRatio(mGroupKey, s) && targetIndex < 0)
                    targetIndex = i;
            } else {
                if(RankNumManager.getItemRatio(rankItem.getGroupKey(), rankItem.getCId()) < RankNumManager.getItemRatio(mGroupKey, s))
                    targetIndex = i;
            }
            i++;
        }

        //没有变化
        if(targetIndex == -1) {

        } else {
            mRankList.remove(currentIndex);
            if(targetIndex >= mRankList.size())
                mRankList.add(rankItem.getCId());
            else
                mRankList.add(targetIndex, rankItem.getCId());
        }

        for(i=0; i<getChildCount(); i++) {
            RankItem item = (RankItem) getChildAt(i);
            if(item.getCId().equalsIgnoreCase(mRankList.get(0))) {
                bringChildToFront(item);
                return;
            }
        }
    }

    private void relayoutItems(final HashMap<String, Integer> targets) {
        if(mTranslationYSet == null || targets == null || mTranslationYSet.size() != targets.size())
            return;
        ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();

                for(int i=0; i<getChildCount(); i++) {
                    RankItem item = (RankItem) getChildAt(i);
                    String id = item.getCId();
                    float ypos = mTranslationYSet.get(id) + value*(targets.get(id) - mTranslationYSet.get(id));
                    item.setTranslationY(ypos);
                }
            }
        });
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                //update value
                Iterator<Map.Entry<String, Integer>> iterator = targets.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, Integer> entry = iterator.next();
                    mTranslationYSet.put(entry.getKey(), entry.getValue());
                }
            }
        });
        anim.setDuration(500);
        anim.start();
    }

}
